package com.chung.sean.maptest;

import java.util.ArrayList;
import java.util.List;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;

/**
 * Implements Google Maps on Android devices. Includes test class and ability to separate 
 * CSV style data strings to map. Currently there is NO API key being used in "mapmain.xml"
 * The map will NOT load until a key is found and added to the project. 
 * The place to input the key is clearly marked/commented in the .xml file.
 * Information on getting an API key can be found here: https://developers.google.com/maps/documentation/android/mapkey
 * 
 * NOTE: The SHA1 hash will NOT give you a correct API key. Google may spit one out, 
 * but it will NOT work. In the case you are only seeing a SHA1 key come out on your side, 
 * enter the following command instead (only change is the -v):
 * 
 * keytool -list -v -alias androiddebugkey -keystore <path to keystore> -storepass android -keypass android
 * 
 * This will give you the MD5.
 * 
 * @author Sean
 *
 */
public class MapTest extends MapActivity {

  private List<String> locations,testCases,data;
  private MapView map = null;
  private MyLocationOverlay current = null;
  private CheckBox satellite;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map);
    
    // Testing data.
    testCases = new ArrayList<String>();
    testCases.add("33,123,hello android");
    testCases.add("34,50,132144 242rhkd !@!(&^( 3gfiwde");
    testCases.add("20,100,asdsadasf");
    testCases.add("-100,100,asdsadasf");
    testCases.add("-100,-100,tessssttttt");
    testCases.add("180,180,1234567890765432hu4w7364yrhn32524grbf    ty454tge");
    testCases.add("0,0,asdsadasf");
    testCases.add("-100.47289471,100.4281471,asdsadasf");
    testCases.add("89.13231,-100.912792,asdsadasf");
    
    data = new ArrayList<String>();
    locations = new ArrayList<String>();
    load();
  }

  /**
   * Loads the initial configuration for the Maps class.
   */
  private void load() {       
    map = (MapView)findViewById(R.id.mapview);   
    satellite = (CheckBox)findViewById(R.id.satellite);
    satellite.setOnClickListener(satelliteOnClickListener);
    
    Button myLoadMapButton = (Button)findViewById(R.id.loadmap);
    myLoadMapButton.setOnClickListener(loadMapOnClickListener);
  }

  Button.OnClickListener loadMapOnClickListener = new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
        getData(testCases);
        loadMap();  
    }};
  
  /**
   * Gets the data from saved files.
   * 
   * @param files Array list of file data in strings.
   */
  private void getData(List<String> files) {  
    for (String data : files) {
      parseContent(data);
    }
  }
  
  /**
   * Parses file contents on commas(,).
   * 
   * @param content String to parse
   */
  private void parseContent (String content) {
    String[] fileContent = content.split(","); // Separate content on comma.
    
    // Find data values.
    String latitude = fileContent[0];
    String longitude = fileContent[1]; 
    String context = fileContent[2];

    // I'm sure there's a more "elegant" way to do this, but I can't think of a reasonable one.
    data.add("Latitude: " + latitude + "\n" + "Longitude: " + longitude + "\n" + "Context: " + context);
    
    locations.add(latitude);
    locations.add(longitude);
  }
  
  /**
   * Creates aand returns new GeoPoint based on a latitude and longitude string.
   * 
   * @param latitude String latitude
   * @param longitude String longitude
   * @return GeoPoint to plot on map
   */
  private GeoPoint getPoint(String latitude, String longitude) {
    double exactLat = Double.parseDouble(latitude);
    double exactLong = Double.parseDouble(longitude);
    GeoPoint point = new GeoPoint((int)(exactLat * 1000000.0), 
                                   (int)(exactLong * 1000000.0));
    return point;
  }
  
  /**
   * Load the initial configuration for the map. Set zoom controls and initial level.
   * Adds the "pin" image to map overlay.
   */
  private void loadMap() {
    map.setBuiltInZoomControls(true);
    map.getController().setZoom(0);
    
    // Change the drawable resource "ic_launcher" to change "pin" type.
    Drawable pin = getResources().getDrawable(R.drawable.ic_launcher);
    
    // Make sure pin resizes on zoom(s).
    pin.setBounds(0, 0, pin.getIntrinsicWidth(),pin.getIntrinsicHeight());
    map.getOverlays().add(new SitesOverlay(pin));
    current = new MyLocationOverlay(this, map);
    map.getOverlays().add(current);
  }
  
  @Override
  public void onResume() {
    super.onResume();    
  }   
  
  @Override
  public void onPause() {
    super.onPause();  
  } 
  
  @Override
  protected boolean isRouteDisplayed() {
    return false;
  }
  
  /**
   * Changes to "Satellite" view.
   */
  private void setSatellite() {
    map.setSatellite(satellite.isChecked());
  }
  
  private CheckBox.OnClickListener satelliteOnClickListener = new CheckBox.OnClickListener() {
    public void onClick(View v) {
      setSatellite();
    }
  };
     
  /**
   * Custom overlay class. Creates an overlay of specific points to place on map.
   * Clicking on points will reveal more information about them.
   * 
   * @author Sean
   *
   */
  private class SitesOverlay extends ItemizedOverlay<OverlayItem> {
    private List<OverlayItem> items = new ArrayList<OverlayItem>();
    
    public SitesOverlay(Drawable marker) {     
      super(marker);      
      boundCenterBottom(marker);

      String [] points = locations.toArray(new String[locations.size()]);
      String [] deviceData = data.toArray(new String[data.size()]);
      int count = 0;
      
      // Add new points to map.
      for (int i = 0; i < points.length; i++) {       
        items.add(new OverlayItem(getPoint(points[i],points[i++]),null,deviceData[count]));
        count++;
      }      
      populate();
    }
    
    @Override
    protected OverlayItem createItem(int i) {
      return(items.get(i));
    }
    
    @Override
    protected boolean onTap(int i) {
      // It is possible to do a more custom, pretty dialog box thing here, 
      // but there were problems in the emulator in terms of resource usage. 
      // Could be OK on an actual device??
      Toast.makeText(MapTest.this,items.get(i).getSnippet(),Toast.LENGTH_LONG).show();      
      return(true);
    }
    
    @Override
    public int size() {
      return(items.size());
    }
  }
}